home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / DirectX / dx9sdkcp.exe / SDK (C++) / Bin / DXUtils / Visual Studio 6.0 Wizards / DMToolWizard.awx / TEMPLATE / PARAM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-11  |  16.2 KB  |  574 lines

  1. //------------------------------------------------------------------------------
  2. // File: Param.cpp
  3. //
  4. // Desc: DirectMusicTool Wizard generated code - implementation of 
  5. //         CParamsManager class.
  6. //
  7. // Copyright (c) Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9. #include <stdio.h>
  10.  
  11. #include <windows.h>
  12. #include <medparam.h>
  13. #include "alist.h"
  14. #include "param.h"
  15. #include "dmerror.h"
  16. #include "math.h"
  17. #include "validate.h"
  18.  
  19. #pragma warning(disable:4296)       
  20.  
  21. CCurveList::~CCurveList()
  22. {
  23.     while(this->GetHead())
  24.     {
  25.         delete this->RemoveHead();
  26.     }
  27. }
  28.  
  29. CParamsManager::CParamsManager()
  30.   
  31. {
  32.     m_fDirty = FALSE;
  33.     m_cTimeFormats = 0;
  34.     m_pguidTimeFormats = NULL;
  35.     m_guidCurrentTimeFormat = GUID_NULL;
  36.     m_cParams = 0;
  37.     m_pCurveLists = NULL;
  38.     m_pParamInfos = NULL;
  39.     m_dwActiveBits = 0;
  40.     InitializeCriticalSection(&m_ParamsCriticalSection);
  41. }
  42.  
  43. CParamsManager::~CParamsManager()
  44. {
  45.     delete[] m_pguidTimeFormats;
  46.     delete[] m_pCurveLists;
  47.     delete[] m_pParamInfos;
  48.     DeleteCriticalSection(&m_ParamsCriticalSection);
  49. }
  50.  
  51. HRESULT CParamsManager::InitParams(DWORD cTimeFormats, const GUID *pguidTimeFormats, DWORD dwFormatIndex, MP_TIMEDATA mptdTimeData, DWORD cParams, ParamInfo *pParamInfo)
  52. {
  53.     //check that the index is in a valid range
  54.     if (0 > dwFormatIndex || dwFormatIndex >= cTimeFormats || cParams > sizeof(DWORD) * 8)
  55.         return E_INVALIDARG;
  56.         
  57.     m_pCurveLists = new CCurveList[cParams];
  58.     if (!m_pCurveLists)
  59.         return E_OUTOFMEMORY;
  60.  
  61.     // save the time formats
  62.     m_pguidTimeFormats = new GUID[cTimeFormats];
  63.     if (!m_pguidTimeFormats)
  64.         return E_OUTOFMEMORY;
  65.         
  66.     for (DWORD dwIndex = 0; dwIndex < cTimeFormats; dwIndex++)
  67.     {
  68.         memcpy(&m_pguidTimeFormats[dwIndex], &pguidTimeFormats[dwIndex], sizeof(*pguidTimeFormats));
  69.     }
  70.  
  71.     // save the count of formats
  72.     m_cTimeFormats = cTimeFormats;
  73.  
  74.     // save the current time format
  75.     m_guidCurrentTimeFormat = m_pguidTimeFormats[dwFormatIndex];
  76.  
  77.     // save the TimeData
  78.     m_mptdCurrentTimeData = mptdTimeData;
  79.  
  80.     // save the parameter info
  81.     m_pParamInfos
  82.     = new ParamInfo[cParams];
  83.     if (!m_pParamInfos)
  84.         return E_OUTOFMEMORY;
  85.     for (dwIndex = 0; dwIndex < cParams; dwIndex++)
  86.     {
  87.         if (pParamInfo[dwIndex].dwIndex < cParams)
  88.         {
  89.             memcpy(&m_pParamInfos[pParamInfo[dwIndex].dwIndex],&pParamInfo[dwIndex],sizeof(ParamInfo));
  90.         }
  91.     }
  92.     m_cParams = cParams;
  93.  
  94.     return S_OK;
  95. }
  96.  
  97. HRESULT CParamsManager::GetParamCount(DWORD *pdwParams)
  98.  
  99. {
  100.     if (pdwParams == NULL)
  101.         return E_POINTER;
  102.     
  103.     *pdwParams = m_cParams;
  104.     return S_OK;
  105. }
  106.  
  107. HRESULT CParamsManager::GetParamInfo(DWORD dwParamIndex,MP_PARAMINFO *pInfo)
  108.  
  109. {
  110.     if (!pInfo)
  111.     {
  112.         return E_POINTER;
  113.     }
  114.     if (dwParamIndex < m_cParams)
  115.     {
  116.         *pInfo = m_pParamInfos[dwParamIndex].MParamInfo;
  117.         return S_OK;
  118.     }
  119.     else
  120.     {
  121.         return E_INVALIDARG;
  122.     }
  123. }
  124.  
  125. HRESULT CParamsManager::GetParamText(DWORD dwParamIndex,WCHAR **ppwchText)
  126.  
  127. {
  128.     if (!ppwchText)
  129.     {
  130.         return E_POINTER;
  131.     }
  132.     if (dwParamIndex < m_cParams)
  133.     {
  134.         // write string of format: "Label\0Unit\0Enums1\0Enum2\0...EnumN\0\0"
  135.         ParamInfo &pinfo = m_pParamInfos[dwParamIndex];
  136.         int iUnit = wcslen(pinfo.MParamInfo.szLabel) + 1; // begin writing unit text here
  137.         int iEnums = iUnit + wcslen(pinfo.MParamInfo.szUnitText) + 1; // begin writing enum text here
  138.         int iEnd = iEnums + wcslen(pinfo.pwchText) + 1; // write the final (second) null terminator here
  139.         WCHAR *pwsz = static_cast<WCHAR *>(CoTaskMemAlloc((iEnd + 1) * sizeof(WCHAR)));
  140.         if (!pwsz)
  141.             return E_OUTOFMEMORY;
  142.  
  143.         // wcscpy will write into various points of the string, neatly terminating each with a null
  144.         wcscpy(pwsz, pinfo.MParamInfo.szLabel);
  145.         wcscpy(pwsz + iUnit, pinfo.MParamInfo.szUnitText);
  146.         wcscpy(pwsz + iEnums, pinfo.pwchText);
  147.  
  148.         // The text field was defined with commas to separate the enum values.
  149.         // Replace them with NULL characters now.
  150.         for (WCHAR *pwch = pwsz + iEnums; *pwch; ++pwch)
  151.         {
  152.             if (*pwch == L',')
  153.                 *pwch = L'\0';
  154.         }
  155.  
  156.         pwsz[iEnd] = L'\0';
  157.         
  158.         *ppwchText = pwsz;
  159.         return S_OK;
  160.     }
  161.     else
  162.     {
  163.         return E_INVALIDARG;
  164.     }
  165. }
  166.  
  167. HRESULT CParamsManager::GetNumTimeFormats(DWORD *pdwNumTimeFormats)
  168.  
  169. {
  170.     if (!pdwNumTimeFormats)
  171.     {
  172.         return E_POINTER;
  173.     }
  174.     *pdwNumTimeFormats = m_cTimeFormats;
  175.     return S_OK;
  176. }
  177.  
  178. HRESULT CParamsManager::GetSupportedTimeFormat(DWORD dwFormatIndex,GUID *pguidTimeFormat)
  179.  
  180. {
  181.     if (!pguidTimeFormat)
  182.     {
  183.         return E_POINTER;
  184.     }
  185.     if (dwFormatIndex >= m_cTimeFormats)
  186.     {
  187.         return E_INVALIDARG;
  188.     }
  189.     *pguidTimeFormat = m_pguidTimeFormats[dwFormatIndex];
  190.     return S_OK;
  191. }
  192.  
  193. HRESULT CParamsManager::GetCurrentTimeFormat( GUID *pguidTimeFormat,MP_TIMEDATA *pTimeData)
  194.  
  195. {
  196.     HRESULT hr = S_OK;
  197.     
  198.     // Parameter Validation
  199.     if ((pguidTimeFormat == NULL) || (pTimeData == NULL))
  200.     {
  201.         hr = E_POINTER;
  202.     }
  203.  
  204.     // Return the values
  205.     if (SUCCEEDED(hr))
  206.     {
  207.         *pguidTimeFormat = m_guidCurrentTimeFormat;
  208.         *pTimeData = m_mptdCurrentTimeData;
  209.     }
  210.     
  211.     return hr;
  212. }
  213.  
  214.  
  215. HRESULT CParamsManager::CopyParamsFromSource( CParamsManager * pSource)
  216.  
  217. {
  218.     HRESULT hr = S_OK;
  219.     DWORD dwIndex;
  220.  
  221.     for (dwIndex = 0; dwIndex < m_cTimeFormats; dwIndex++)
  222.     {
  223.         if (pSource->m_guidCurrentTimeFormat == m_pguidTimeFormats[dwIndex])
  224.         {
  225.             break;
  226.         }
  227.     }
  228.     
  229.     
  230.     hr = InitParams(pSource->m_cTimeFormats, pSource->m_pguidTimeFormats, dwIndex, pSource->m_mptdCurrentTimeData, pSource->m_cParams,pSource->m_pParamInfos);
  231.     if (SUCCEEDED(hr))
  232.     {
  233.         for (dwIndex = 0; dwIndex < m_cParams; dwIndex++)
  234.         {
  235.             CCurveItem *pCurve = pSource->m_pCurveLists[dwIndex].GetHead();
  236.             for (;pCurve;pCurve = pCurve->GetNext())
  237.             {
  238.                 CCurveItem *pNew = new CCurveItem;
  239.                 if (!pNew) 
  240.                 {
  241.                     return E_OUTOFMEMORY;
  242.                 }
  243.                 pNew->m_Envelope = pCurve->m_Envelope;
  244.                 m_pCurveLists[dwIndex].AddTail(pNew);
  245.             }
  246.         }
  247.     }
  248.     return hr;
  249. }
  250.  
  251. void
  252. CParamsManager ::UpdateActiveParams(REFERENCE_TIME rtTime, UpdateCallback &rThis)
  253. {
  254.     if (!m_dwActiveBits)
  255.         return; // nothing to recalc
  256.  
  257.     DWORD dwBit = 1;
  258.     for (DWORD dwIndex = 0; dwIndex < m_cParams; dwIndex++, dwBit = dwBit << 1)
  259.     {
  260.         if (m_dwActiveBits & dwBit)
  261.         {
  262.             float fVal = 0;
  263.             HRESULT hr = GetParamFloat(dwIndex, rtTime, &fVal);
  264.             rThis.SetParamUpdate(dwIndex, fVal);
  265.             if (hr == S_FALSE)
  266.                 m_dwActiveBits &= ~dwBit; // we're beyond the last curve, don't need to recalc next time
  267.  
  268.             //TraceI(6, "DMTool value: time %I64d, param #%d, current value %hf\n", rtTime, dwIndex, fVal);
  269.         }
  270.     }
  271. }
  272.  
  273. inline float ValRange(float valToClip, float valMin, float valMax)
  274. {
  275.     return valToClip < valMin
  276.                 ? valMin
  277.                 : (valToClip > valMax ? valMax : valToClip);
  278. }
  279.  
  280. HRESULT CParamsManager::GetParamFloat(DWORD dwParamIndex,REFERENCE_TIME rtTime,float *pval)
  281. {
  282.     HRESULT hr = S_OK;
  283.  
  284.     if (dwParamIndex >= m_cParams)
  285.         return E_INVALIDARG;
  286.  
  287.     EnterCriticalSection(&m_ParamsCriticalSection);
  288.     CCurveList *pList = &m_pCurveLists[dwParamIndex];
  289.     ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  290.  
  291.     // if no points, then neutral value
  292.     CCurveItem *pCurveHead = pList->GetHead();
  293.     if (!pCurveHead)
  294.     {
  295.         *pval = pInfo->MParamInfo.mpdNeutralValue;
  296.         LeaveCriticalSection(&m_ParamsCriticalSection);
  297.         return S_FALSE;
  298.     }
  299.  
  300.     // Find the curve during or before the requested time
  301.     // If the time is during a curve, we will use that.
  302.     // If not, we need the end value of the previous curve.
  303.     // Our list keeps these in backwards order, so we are scanning from the 
  304.     // highest point in time backwards.
  305.  
  306.     for (CCurveItem *pCurve = pCurveHead; pCurve && pCurve->m_Envelope.rtStart > rtTime;pCurve = pCurve->GetNext());
  307.  
  308.     // If there is no pCurve, there was no curve prior to or during rtTime. Give up.
  309.     if (!pCurve)
  310.     {
  311.         *pval = pInfo->MParamInfo.mpdNeutralValue;
  312.         LeaveCriticalSection(&m_ParamsCriticalSection);
  313.         return S_OK;
  314.     }
  315.     // Now, if pCurve ends before the requested time,
  316.     // return the final value of pCurve, since that will hold until the start of the next curve.
  317.     if (pCurve->m_Envelope.rtEnd < rtTime)
  318.     {
  319.         *pval = pCurve->m_Envelope.valEnd;
  320.         LeaveCriticalSection(&m_ParamsCriticalSection);
  321.         if (pCurve == pCurveHead)
  322.             return S_FALSE; // past last curve
  323.         else
  324.             return S_OK; // there are more curves ahead
  325.     }
  326.  
  327.     // If we get this far, the curve must bound rtTime.
  328.  
  329.     if (pCurve->m_Envelope.iCurve & MP_CURVE_JUMP)
  330.     {
  331.         *pval = pCurve->m_Envelope.valEnd;
  332.         LeaveCriticalSection(&m_ParamsCriticalSection);
  333.         return S_OK;
  334.     }
  335.  
  336.     REFERENCE_TIME rtTimeChange = pCurve->m_Envelope.rtEnd - pCurve->m_Envelope.rtStart;
  337.     REFERENCE_TIME rtTimeIntermediate = rtTime - pCurve->m_Envelope.rtStart; 
  338.  
  339.     float fltScalingX = static_cast<float>(rtTimeIntermediate) / rtTimeChange; // horizontal distance along curve between 0 and 1
  340.     float fltScalingY; // height of curve at that point between 0 and 1 based on curve function
  341.     switch (pCurve->m_Envelope.iCurve)
  342.     {
  343.     case MP_CURVE_SQUARE:
  344.         fltScalingY = fltScalingX * fltScalingX;
  345.         break;
  346.     case MP_CURVE_INVSQUARE:
  347.         fltScalingY = (float) sqrt(fltScalingX);
  348.         break;
  349.     case MP_CURVE_SINE:
  350.         // ºº Maybe we should have a lookup table here?
  351.         fltScalingY = (float) (sin(fltScalingX * 3.1415926535 - (3.1415926535/2)) + 1) / 2;
  352.         break;
  353.     case MP_CURVE_LINEAR:
  354.     default:
  355.         fltScalingY = fltScalingX;
  356.     }
  357.  
  358.     // Find out if we need to pull the start point from the previous curve,
  359.     // the default neutral value, or the current curve.
  360.     float fStartVal = pCurve->m_Envelope.valStart;
  361.     if (pCurve->m_Envelope.flags & MPF_ENVLP_BEGIN_NEUTRALVAL)
  362.     {
  363.         fStartVal = pInfo->MParamInfo.mpdNeutralValue;
  364.     }
  365.     // Currentval, if it exists, will override neutralval.
  366.     if (pCurve->m_Envelope.flags & MPF_ENVLP_BEGIN_CURRENTVAL)
  367.     {
  368.         // Take advantage of the fact that these are inserted in backwards order.
  369.         // Scan for the previous curve that ends before this time.
  370.         CCurveItem *pPrevious = pCurve->GetNext();
  371.            for (;pPrevious && pPrevious->m_Envelope.rtEnd > rtTime;pPrevious = pPrevious->GetNext());
  372.         if (pPrevious)
  373.         {
  374.             fStartVal = pPrevious->m_Envelope.valEnd;
  375.         }
  376.     }
  377.     
  378.     // Apply that scaling to the range of the actual points
  379.     *pval = (pCurve->m_Envelope.valEnd - fStartVal) * fltScalingY + fStartVal;
  380.  
  381.     LeaveCriticalSection(&m_ParamsCriticalSection);
  382.     return hr;
  383. }
  384.  
  385. HRESULT CParamsManager::GetParamInt(DWORD dwParamIndex,REFERENCE_TIME rt,long *pval)
  386.  
  387. {
  388.     HRESULT hr = E_POINTER;
  389.     if (pval)
  390.     {
  391.         float fVal;
  392.         hr = GetParamFloat(dwParamIndex,rt,&fVal);
  393.         if (SUCCEEDED(hr))
  394.         {
  395.             *pval = (long) (fVal + 1/2);    // Round.
  396.         }
  397.     }
  398.     return hr;
  399. }
  400.  
  401. //////////////////////////////////////////////////////////////////////
  402. // IMediaParams
  403.  
  404. HRESULT CParamsManager::GetParam(DWORD dwParamIndex,MP_DATA *pValue)
  405. {
  406.     V_INAME(CParams::GetParam);
  407.     V_PTR_WRITE(pValue, MP_DATA);
  408.  
  409.     if (dwParamIndex >= m_cParams)
  410.         return E_INVALIDARG;
  411.  
  412.     EnterCriticalSection(&m_ParamsCriticalSection);
  413.  
  414.     CCurveList *pList = &m_pCurveLists[dwParamIndex];
  415.     ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  416.     // if no points, then neutral value
  417.     CCurveItem *pCurve = pList->GetHead();
  418.     if (pCurve)
  419.     {
  420.         *pValue = pCurve->m_Envelope.valEnd;
  421.     }
  422.     else
  423.     {
  424.         *pValue = pInfo->MParamInfo.mpdNeutralValue;
  425.     }
  426.     LeaveCriticalSection(&m_ParamsCriticalSection);
  427.     return S_OK;
  428. }
  429.  
  430. HRESULT CParamsManager::SetParam(DWORD dwParamIndex,MP_DATA value)
  431. {
  432.     V_INAME(CParams::SetParam);
  433.     
  434.     if (dwParamIndex >= m_cParams)
  435.     {
  436.         return E_INVALIDARG;
  437.     }
  438.  
  439.     EnterCriticalSection(&m_ParamsCriticalSection);
  440.     m_fDirty = TRUE;
  441.     CCurveList *pList = &m_pCurveLists[dwParamIndex];
  442.     ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  443.     // If we've already got a list, just force the most recent curve item to this value.
  444.     // Otherwise, create a node and add it.
  445.     CCurveItem *pCurve = pList->GetHead();
  446.     if (!pCurve)
  447.     {
  448.         pCurve = new CCurveItem;
  449.         if (pCurve)
  450.         {
  451.             pCurve->m_Envelope.rtStart =    0x8000000000000000; // Max negative.
  452.             pCurve->m_Envelope.rtEnd =      0x7FFFFFFFFFFFFFFF; // Max positive.
  453.             pCurve->m_Envelope.flags = 0;
  454.             pList->AddHead(pCurve);
  455.         }
  456.         else 
  457.         {
  458.             LeaveCriticalSection(&m_ParamsCriticalSection);
  459.             return E_OUTOFMEMORY;
  460.         }
  461.     }
  462.     pCurve->m_Envelope.valStart = value;
  463.     pCurve->m_Envelope.valEnd = value;
  464.     pCurve->m_Envelope.iCurve = MP_CURVE_JUMP;
  465.     LeaveCriticalSection(&m_ParamsCriticalSection);
  466.  
  467.     return S_OK;
  468. }
  469.  
  470. HRESULT CParamsManager::AddEnvelope(
  471.         DWORD dwParamIndex,
  472.         DWORD cPoints,
  473.         MP_ENVELOPE_SEGMENT *ppEnvelope)
  474. {
  475.     V_INAME(CParams::AddEnvelope);
  476.     V_PTR_READ(ppEnvelope, *ppEnvelope);
  477.  
  478.     if (dwParamIndex >= m_cParams)
  479.         return E_INVALIDARG;
  480.  
  481.     if (!m_pParamInfos)
  482.         return DMUS_E_NOT_INIT;
  483.  
  484.     HRESULT hr = S_OK;
  485.     EnterCriticalSection(&m_ParamsCriticalSection);
  486.     m_fDirty = TRUE;
  487.  
  488.     CCurveList *pList = &m_pCurveLists[dwParamIndex];
  489.     ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  490.  
  491.     DWORD dwCount;
  492.     for (dwCount = 0; dwCount < cPoints; dwCount++)
  493.     {
  494.         CCurveItem *pCurve = new CCurveItem;
  495.         if (!pCurve) 
  496.         {
  497.             hr = E_OUTOFMEMORY;
  498.             break;
  499.         }
  500.         pCurve->m_Envelope = ppEnvelope[dwCount];
  501.         pCurve->m_Envelope.valEnd = ValRange(pCurve->m_Envelope.valEnd, 
  502.             pInfo->MParamInfo.mpdMinValue, pInfo->MParamInfo.mpdMaxValue);
  503.         pCurve->m_Envelope.valStart = ValRange(pCurve->m_Envelope.valStart, 
  504.             pInfo->MParamInfo.mpdMinValue, pInfo->MParamInfo.mpdMaxValue);
  505.         pList->AddHead(pCurve);
  506.         m_dwActiveBits |= 1 << dwParamIndex; // next call to UpdateActiveParams will ensure the parameter's value is recalculated
  507.  
  508.         //TraceI(6, "DMTool envelope: time %I64d-%I64d, param #%d, value %hf-%hf\n",
  509.         //        pCurve->m_Envelope.rtStart, pCurve->m_Envelope.rtEnd,
  510.         //        dwParamIndex, pCurve->m_Envelope.valStart, pCurve->m_Envelope.valEnd);
  511.     }
  512.  
  513.     LeaveCriticalSection(&m_ParamsCriticalSection);
  514.  
  515.     return hr;
  516. }
  517.  
  518. HRESULT CParamsManager::FlushEnvelope(
  519.         DWORD dwParamIndex,
  520.         REFERENCE_TIME refTimeStart,
  521.         REFERENCE_TIME refTimeEnd)
  522. {
  523.     if (dwParamIndex >= m_cParams)
  524.         return E_INVALIDARG;
  525.  
  526.     if (!m_pParamInfos)
  527.         return DMUS_E_NOT_INIT;
  528.  
  529.     if (refTimeStart >= refTimeEnd)
  530.         return E_INVALIDARG;
  531.  
  532.     EnterCriticalSection(&m_ParamsCriticalSection);
  533.     m_fDirty = TRUE;
  534.     CCurveList *pList = &m_pCurveLists[dwParamIndex];
  535.     ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  536.     CCurveList TempList;
  537.     CCurveItem *pCurve;
  538.     while ((pCurve = pList->RemoveHead()) != NULL)
  539.     {
  540.         if ((pCurve->m_Envelope.rtStart >= refTimeStart) && 
  541.             (pCurve->m_Envelope.rtEnd <= refTimeEnd))
  542.         {
  543.             delete pCurve;
  544.         }
  545.         else 
  546.         {
  547.             TempList.AddHead(pCurve);
  548.         }
  549.     }
  550.     while ((pCurve = TempList.RemoveHead()) != NULL)
  551.     {
  552.         pList->AddHead(pCurve);
  553.     }
  554.     LeaveCriticalSection(&m_ParamsCriticalSection);
  555.  
  556.     return S_OK;
  557. }
  558.  
  559. HRESULT CParamsManager::SetTimeFormat(
  560.         GUID guidTimeFormat,
  561.         MP_TIMEDATA mpTimeData)
  562. {
  563.     for (DWORD dwIndex = 0; dwIndex < m_cTimeFormats; dwIndex++)
  564.     {
  565.         if (guidTimeFormat == m_pguidTimeFormats[dwIndex])
  566.         {
  567.             m_guidCurrentTimeFormat = m_pguidTimeFormats[dwIndex];
  568.             return S_OK;
  569.         }
  570.     }
  571.  
  572.     return E_INVALIDARG;
  573. }
  574.